﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using A2DFramework.MVCFramework.Descriptors;
using A2DFramework.MVCFramework.HttpAttributes;

namespace A2DFramework.MVCFramework.Registry
{
    public static class ControllerRegistry
    {
        private static Dictionary<string, List<ControllerDescriptor>> controllers = new Dictionary<string, List<ControllerDescriptor>>();

        /// <summary>
        /// 找到所有dll，分解class，后缀为Controller的则加入Dictionary
        /// </summary>
        public static void Register()
        {
            var lst = AppDomain.CurrentDomain.GetAssemblies().ToList().OrderBy(o=>o.FullName).ToList();
            lst = lst.Where(w => !w.FullName.StartsWith("Microsoft", StringComparison.OrdinalIgnoreCase)).ToList();
            lst = lst.Where(w => !w.FullName.StartsWith("System", StringComparison.OrdinalIgnoreCase)).ToList();
            lst = lst.Where(w => !w.FullName.StartsWith("mscorlib", StringComparison.OrdinalIgnoreCase)).ToList();
            
            foreach(var item in lst)
            {
                List<Type> types=item.GetTypes().ToList().Where(w=>w.FullName.EndsWith("Controller")).ToList();
                foreach (var type in types)
                {
                    string key = type.Name.ToLower();

                    ControllerDescriptor controllerDescriptor=new ControllerDescriptor();

                    controllerDescriptor.ControllerType = type;
                    controllerDescriptor.Namespace = type.Namespace;

                    if (!controllers.ContainsKey(key))
                        controllers[key] = new List<ControllerDescriptor>();

                    controllers[key].Add(controllerDescriptor);

                    //继续填充ControllerDescriptor
                    MethodInfo[] methods=type.GetMethods(BindingFlags.Static|BindingFlags.Public);
                    foreach(var method in methods)
                    {
                        MethodDescriptor methodDescriptor = new MethodDescriptor();
                        methodDescriptor.MethodName = method.Name;

                        ParameterInfo[] parameters=method.GetParameters();
                        foreach(var parameter in parameters)
                        {
                            ParameterDescriptor parameterDescriptor = new ParameterDescriptor();

                            parameterDescriptor.ParameterType = parameter.ParameterType;

                            var fieldSources = parameter.GetCustomAttributes(typeof(HttpFieldSourceAttribute), true) as HttpFieldSourceAttribute[];
                            if (fieldSources != null && fieldSources.Length > 0)
                            {
                                var att = fieldSources.First();

                                parameterDescriptor.KeyInSource = att.FieldKey;
                                if (att is HttpCookieAttribute)
                                    parameterDescriptor.SourceLocation = SourceLocation.Cookies;
                                else if (att is HttpFormAttribute)
                                    parameterDescriptor.SourceLocation = SourceLocation.From;
                                else if (att is HttpHeaderAttribute)
                                    parameterDescriptor.SourceLocation = SourceLocation.Headers;
                                else if (att is HttpQueryStringAttribute)
                                    parameterDescriptor.SourceLocation = SourceLocation.QueryString;
                                else
                                    parameterDescriptor.SourceLocation = SourceLocation.Any;
                            }
                            else
                            {
                                parameterDescriptor.KeyInSource = parameter.Name;
                            }

                            methodDescriptor.ParameterDescriptors.Add(parameterDescriptor);
                        }

                        controllerDescriptor.MethodDescriptors.Add(methodDescriptor);
                    }
                }
            }

        }


        internal static ControllerDescriptor Resolve(string key)
        {
            key = key.ToLower();
            if (!controllers.ContainsKey(key))
                return null;

            return controllers[key].First();
        }
    }
}
